/*------------------------------------------------------------------------------
* GeoVISTA Center, Penn State Geography Deptartment*
* Copyright (c), 2002, GeoVISTA Center
* All Rights Researved.
*
* Original Authors: Frank Hardisty, Bonan Li
* $Author: bonan_li $
*
* $Date: 2004/03/03 19:03:11 $
*
* $Id: LayerPolygonExtension.java,v 1.3 2004/03/03 19:03:11 bonan_li Exp $
*
* To Do:
*
 ------------------------------------------------------------------------------*/

package edu.psu.geovista.app.map;

import edu.psu.geovista.symbollibrary.SymbolInterface;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;

/**
 * put your documentation comment here
 */
public class LayerPolygonExtension
    extends LayerShapeExtension implements LayerInterface{

  private SymbolInterface[] symbols = null;

  public void setSymbols(SymbolInterface[] symbols) {
    this.symbols = symbols;
  }

  public void render(Graphics2D g2) {

    if (this.objectColors == null) {
      System.out.println("LayerShape, render called on null objectColors");
      return;
    }
    if (g2 == null) {
      throw new IllegalArgumentException(this.toString() +
          " Null graphics passed in to render(Graphics2D).");
    }

    if (this.isAuxiliary) {
      System.out.println("rendering auxiliary layer....polygon. ");
      super.renderAux(g2);
      return;
    }

    for (int path = 0; path < spatialData.length; path++) {
      this.renderObservationNoIndication(path, g2);
    }
  } //end method


  public void renderObservation(int obs, Graphics2D g2) {
    if (obs < 0) {
      return;
    }
    if (this.objectColors.length <= obs) {
      return;
    }

    Shape shp = spatialData[obs];
    if (fisheyes != null) {
      shp = fisheyes.transform(shp);
    }

    g2.setStroke(this.defaultStroke);
    Color color = this.objectColors[obs];
    g2.setColor(color);
    g2.fill(shp);

    if (this.defaultStrokeWidth >= 0.1f) {
      g2.setColor(this.colorLine);
      g2.draw(shp);
    }

    //Here's the place drawing symbols.
    if (this.symbols != null ) {
      shp.getBounds2D().getCenterX();
      shp.getBounds2D().getCenterY();
      this.renderSymbol(this.symbols[obs], shp.getBounds2D().getCenterX(),
                        shp.getBounds2D().getCenterY(), g2);
    }

  }

  private void renderSymbol(SymbolInterface sym, double x, double y,
                            Graphics2D g2d) {
    if (this.symbols != null ||sym!= null) {
      sym.setX( (int) (x + 0.5));
      sym.setY( (int) (y + 0.5));
      sym.draw(g2d);
    }
  }

  public void renderObservationNoIndication(int obs, Graphics2D g2)
  {
    if (obs < 0) {
      return;
    }
    if (this.objectColors.length <= obs) {
      return;
    }

    Shape shp = spatialData[obs];
    if (fisheyes != null) {
      shp = fisheyes.transform(shp);
    }

    if (conditionArray[obs] > -1) {
      g2.setStroke(this.defaultStroke);
      if(!this.selOriginalColorMode || this.selectedObservationsFullIndex[obs] == this.STATUS_SELECTED ||!this.selectionExists){
        Color color = this.objectColors[obs];
        g2.setColor(color);
        g2.fill(shp);
      }

      if (this.defaultStrokeWidth >= 0.1f) {
        g2.setColor(this.colorLine);
        g2.draw(shp);
      }

      if (this.selOriginalColorMode) {
        if (this.selectedObservationsFullIndex[obs] == this.STATUS_NOT_SELECTED &&
            this.selectionExists) {
          g2.setPaint(this.selectionTexture);

          //g2.fill(shp);
        }
      }
        else if (!this.selOriginalColorMode) {
          if (this.selectedObservationsFullIndex[obs] == this.STATUS_SELECTED) {
            g2.setPaint(this.selectionTexture);

            g2.fill(shp);
          }
      }
    }

    //Here's the place drawing symbols.
    if (this.symbols != null ) {
      shp.getBounds2D().getCenterX();
      shp.getBounds2D().getCenterY();
      this.renderSymbol(this.symbols[obs], shp.getBounds2D().getCenterX(),
                        shp.getBounds2D().getCenterY(), g2);
    }
  }

  /*
   * SelectionX1 is expected to be less than selectionX2, same with Y1 and y2.
   * Selected observations should be rendered with the color "colorSelection".
   */
  public void findSelection(int selectionX1, int selectionX2, int selectionY1,
                            int selectionY2) {
    Rectangle selBox = new Rectangle(selectionX1, selectionY1,
                                     selectionX2 - selectionX1,
                                     selectionY2 - selectionY1);

    Vector selObs = new Vector();
    for (int i = 0; i < this.spatialData.length; i++) {
      Rectangle shpBox = this.spatialData[i].getBounds();
      Rectangle2D r2 = null;
      if (selBox.intersects(shpBox)) {
        if (this.spatialData[i].contains(selBox) ||
            this.spatialData[i].intersects(selBox)) {
          selObs.add(new Integer(i));
        } //end if really intersects
      } //end if rough intersects
    } //next
    this.selectedObservations = new int[selObs.size()];
    int j = 0;
    for (Enumeration e = selObs.elements(); e.hasMoreElements(); ) {
      Integer anInt = (Integer) e.nextElement();
      this.selectedObservations[j] = anInt.intValue();
      j++;
    }
  }

  /*
   * selectionX1 is expected to be less than selectionX2, same with Y1 and y2
   */
  public void findSelectionShift(int selectionX1, int selectionX2,
                                 int selectionY1,
                                 int selectionY2) {
    Rectangle selBox = new Rectangle(selectionX1, selectionY1,
                                     selectionX2 - selectionX1,
                                     selectionY2 - selectionY1);

    Vector selObs = new Vector();
    Arrays.sort(this.selectedObservations); //have to do this for the searching
    for (int i = 0; i < this.spatialData.length; i++) {
      Rectangle shpBox = this.spatialData[i].getBounds();
      if (selBox.intersects(shpBox)) {
        if (Arrays.binarySearch(this.selectedObservations, i) < 0) {
          selObs.add(new Integer(i));
        }
      }
    }
    int[] selectedObserCp = new int[this.selectedObservations.length];
    selectedObserCp = (int[]) (this.selectedObservations.clone());
    this.selectedObservations = new int[selectedObserCp.length + selObs.size()];
    int j = 0;
    for (j = 0; j < selectedObserCp.length; j++) {
      this.selectedObservations[j] = selectedObserCp[j];
    }
    for (Enumeration e = selObs.elements(); e.hasMoreElements(); ) {
      Integer anInt = (Integer) e.nextElement();
      this.selectedObservations[j] = anInt.intValue();
      j++;
    }

  }

  public int findIndication(int x, int y) {
    for (int i = 0; i < this.spatialData.length; i++) {
      Rectangle shpBox = this.spatialData[i].getBounds();
      Rectangle2D r2 = null;
      if (shpBox.contains(x, y)) {
        if (this.spatialData[i].contains(x, y)) {
          return i;

        } //end if really intersects
      } //end if rough intersects
    } //next
    //couldn't find anything, so
    return Integer.MIN_VALUE;
  }

}